﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Kinect;

namespace Projet_Synthese
{
    /// <summary>
    /// A class that represents the position of the interaction cursor. Here, it will be our right hand.
    /// </summary>
    public class NUICursor : Microsoft.Xna.Framework.GameComponent
    {

        KinectSensor kinectSensor;

        public KinectSensor KinectSensor
        {
            get { return kinectSensor; }
            set { kinectSensor = value; }
        }

        Vector2 resolution = new Vector2(0.0f);
        private Texture2D curseursTexture;

        private List<Vector2> positions = new List<Vector2>();

        private List<Vector3> positionsMainDroite;

        private List<Vector3> positionsMainGauche;

        public double SensRotation = 0;

        bool selection = false;
        Rectangle sourceRectangle;

        Rectangle destinationMainGauche;

        public Rectangle DestinationMainGauche
        {
            get { return destinationMainGauche; }
            set { destinationMainGauche = value; }
        }
        
        public bool EstSelectionnable
        {
            get{ return selection; }
        }

       public bool EstSelectionné { get; set; } 

       Rectangle destinationMainDroite;

        public Rectangle DestinationMainDroite
        {
            get { return destinationMainDroite; }
            set { destinationMainDroite = value; }
        }
        public Vector3 PositionMainDroite { get; set; }

        public Vector3 PositionMainGauche { get; set; }
        public Vector2 Resolution
        {
            get { return resolution; }
            set { resolution = value; }
        }

        public NUICursor(Game game)
            : base(game)
        {
            PositionMainDroite = Vector3.Zero;
            PositionMainGauche = Vector3.Zero;
        }

        public void Initialize(int width, int height)
        {
            
            resolution = new Vector2((float)width, (float)height);
            try
            {
                kinectSensor = (from sensorToCheck in KinectSensor.KinectSensors
                                where sensorToCheck.Status == KinectStatus.Connected
                                select sensorToCheck).FirstOrDefault();

                TransformSmoothParameters p = new TransformSmoothParameters
                {
                    Smoothing = 0.5f,
                    Correction = 1f,
                    Prediction = 1f,
                    JitterRadius = 0.05f,
                    MaxDeviationRadius = 0.04f
                };


                kinectSensor.SkeletonStream.Enable(p);
                kinectSensor.Start();
                sourceRectangle = new Rectangle(4, 2, 33, 27);
                destinationMainDroite = new Rectangle(0, 0, 12, 12);
                destinationMainGauche = new Rectangle(0, 0, 25, 25);
                positionsMainDroite = new List<Vector3>();
                positionsMainGauche = new List<Vector3>();
                CreateEvent();
            }
            catch (Exception)
            {
            }

            base.Initialize();
        }

        private void CreateEvent()
        {
            kinectSensor.SkeletonFrameReady += new EventHandler<SkeletonFrameReadyEventArgs>(kinectSensor_SkeletonFrameReady);
        }

        private void DetecterCercle(Vector2 pos)
        {
            SensRotation = 0;
            if (!EstSelectionné)
            {
                positions.Clear();
                return;
            }
            positions.Add(pos);

            if(positions.Count ==10)
            {
                int posMinX = 0,posMinY = 0,posMaxX=0, posMaxY = 0;
                for (int i = 0; i < positions.Count; i++)
                {
                    if (positions[posMinX].X > positions[i].X)
                        posMinX = i;
                    else if (positions[posMaxX].X < positions[i].X)
                        posMaxX = i;
                    if (positions[posMinY].Y > positions[i].Y)
                        posMinY = i;
                    else if (positions[posMaxY].Y < positions[i].Y)
                        posMaxY = i;
                }
                if ((positions[posMaxY].Y - positions[posMinY].Y) > 0.005f && (positions[posMaxX].X - positions[posMinX].X) > 0.005f &&
                    (positions[posMaxX].X > positions[posMaxY].X && positions[posMinX].X < positions[posMaxY].X) &&
                    (positions[posMaxX].X > positions[posMinY].X && positions[posMinX].X < positions[posMinY].X) &&
                    (positions[posMaxY].Y > positions[posMaxX].Y && positions[posMinY].Y < positions[posMaxY].Y) &&
                    (positions[posMaxY].Y > positions[posMinX].Y && positions[posMinY].Y < positions[posMinX].Y))
                {
                    if (posMaxX > posMinY && posMinY > posMinX && posMinX > posMaxY || posMinY > posMinX && posMinX > posMaxY && posMaxY > posMaxX ||
                    posMinX > posMaxY && posMaxY > posMaxX && posMaxX > posMinY || posMaxY > posMaxX && posMaxX > posMinY && posMinY > posMinX)
                        SensRotation = -1;
                    else if (posMaxX < posMinY && posMinY < posMinX && posMinX < posMaxY || posMinY < posMinX && posMinX < posMaxY && posMaxY < posMaxX ||
                    posMinX < posMaxY && posMaxY < posMaxX && posMaxX < posMinY || posMaxY < posMaxX && posMaxX < posMinY && posMinY < posMinX)
                        SensRotation = 1;
                }
                positions.Clear();
            }
        }
        void kinectSensor_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
        {
            try
            {
                using (SkeletonFrame skeletonFrame = e.OpenSkeletonFrame())
                {
                    if (skeletonFrame == null)
                        return;
                    Skeleton[] allSkeletons = new Skeleton[skeletonFrame.SkeletonArrayLength];
                    skeletonFrame.CopySkeletonDataTo(allSkeletons);
                    Skeleton playerSkeleton = (from s in allSkeletons where s.TrackingState == SkeletonTrackingState.Tracked select s).FirstOrDefault();
                    
                    Joint rightHandJoint = playerSkeleton.Joints[JointType.HandRight];
                    Joint leftHandJoint = playerSkeleton.Joints[JointType.HandLeft];

                    positionsMainDroite.Add( new Vector3(rightHandJoint.Position.X, rightHandJoint.Position.Y, 0));
                    positionsMainGauche.Add( new Vector3(leftHandJoint.Position.X, leftHandJoint.Position.Y, 0));
                    
                    if (positionsMainDroite.Count >= 3)
                        CalculerPosition(PositionMainDroite, positionsMainDroite, ref destinationMainDroite);
                    if (positionsMainGauche.Count >= 3)
                        CalculerPosition(PositionMainGauche, positionsMainGauche, ref destinationMainGauche);

                    selection = (rightHandJoint.Position.Z + 0.1) > leftHandJoint.Position.Z;
                    DetecterCercle(new Vector2(rightHandJoint.Position.X, rightHandJoint.Position.Y));
                }
            }
            catch
            {
            }

        }
        public void LoadContent(ContentManager content)
        {
           curseursTexture = content.Load<Texture2D>("Base/curseur");
        }
        
        public void Draw(SpriteBatch sprite)
        {
            //sprite.Draw(curseursTexture, DestinationMainDroite, sourceRectangle, Color.White);
            sprite.Draw(curseursTexture, destinationMainGauche, sourceRectangle, Color.White);
        }

        private void CalculerPosition(Vector3 vectPos, List<Vector3> liste, ref Rectangle  destination)
        {
            Vector3 vecteur = Vector3.Zero;
            foreach (Vector3 vector in liste)
                vecteur += vector;
            if (liste.Count > 0)
            {
                vecteur /= liste.Count;
                vectPos += (vecteur - vectPos);
                Point PositionMain = new Point((int)((vectPos.X + 0.5f) * (resolution.X)), (int)(((-1 * vectPos.Y) + 0.5f) * (resolution.Y)));
                destination.X = PositionMain.X % (int)resolution.X;
                destination.Y = PositionMain.Y % (int)resolution.Y;
                liste.Clear();
                liste.Add(vectPos);
            }
        }
    }
}
